package com.hyt.it.ogt.kq.service.admission.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.exception.exception.InvalidRequestException;
import com.hyt.it.ogt.kq.common.gov.enums.GenerateStatusEnum;
import com.hyt.it.ogt.kq.service.admission.IAdmissionTicketInfoService;
import com.hyt.it.ogt.kq.service.admission.IExamineeOperateService;
import com.hyt.it.ogt.kq.service.gov.mapper.admission.ExamineeInfoMapper;
import com.hyt.it.ogt.kq.service.gov.mapper.admission.ExamineeOperateMapper;
import com.hyt.it.ogt.kq.service.gov.model.dto.admission.ExportTicketViewDTO;
import com.hyt.it.ogt.kq.service.gov.model.dto.admission.ExportTicketViewItemDTO;
import com.hyt.it.ogt.kq.service.gov.model.param.admission.ExamineeTicketViewPageParam;
import com.hyt.it.ogt.kq.service.gov.service.obs.CloudObsService;
import com.hyt.it.ogt.kq.service.model.entity.admission.AdmissionTicketInfo;
import com.hyt.it.ogt.kq.service.model.entity.admission.ExamineeOperate;
import com.hyt.model.PageParam;
import com.hyt.progress.service.ProgressManager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;


/**
 * <p>
 * 准考证考生操作表 服务实现类
 * </p>
 *
 * @author yanghuankun@talkweb.com.cn
 * @since 2023-01-10
 */
@Service
@Slf4j
public class ExamineeOperateServiceImpl extends BaseServiceImpl<ExamineeOperateMapper, ExamineeOperate> implements IExamineeOperateService {
	
	private static final Logger LOG = LoggerFactory.getLogger(ExamineeOperateServiceImpl.class);

	@Autowired
	private IAdmissionTicketInfoService iAdmissionTicketInfoService;
	
	@Autowired
	private ExamineeOperateMapper examineeOperateMapper;
	
	@Resource
	private ExamineeInfoMapper examineeInfoMapper;
	
    @Resource
    private CloudObsService cloudObsService;
	
	@Override
	public void exportExamineeOperateList(ExamineeTicketViewPageParam examineeTicketViewPageParam) throws Exception {
	    AdmissionTicketInfo admissionTicketInfo = Optional.ofNullable(iAdmissionTicketInfoService.getById(examineeTicketViewPageParam.getAdmissionTicketInfoId())).orElseThrow(() -> 
            InvalidRequestException.getException(43340502, "无效的准考证"));

		ExcelWriter excelWriter = null;
        try {
            String fileNamePreFix = admissionTicketInfo.getAdmissionTicketName() + "_" + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN) + ".xls"; 
            if(fileNamePreFix.length() > 40) {
                fileNamePreFix = "准考证查看记录" + ".xls"; 
            }
            String fileName = URLEncoder.encode(fileNamePreFix, "UTF-8");
            // 使用 easyExcel 写到 OutputStream
            File achievementDetailListExcel = FileUtil.createTempFile(fileName, true);
            FileOutputStream fileOutputStream = new FileOutputStream(achievementDetailListExcel);

            ProgressManager.updateProgressCurrent(10L, null);
            excelWriter = EasyExcel.write(fileOutputStream).build();
            ProgressManager.updateProgressCurrent(20L, null);
            
            
            // 获取所有的查询考生信息
            List<ExportTicketViewDTO> exportTicketViewDTOs = buildExportTicketViewDtoByCondition(examineeTicketViewPageParam);
            if(CollUtil.isNotEmpty(exportTicketViewDTOs)) {
                LOG.info("# exportTicketViewDTOs size:{}", exportTicketViewDTOs.size());
            }else {
                LOG.info("# exportTicketViewDTOs size null");
            }
            ProgressManager.updateProgressCurrent(40L, null);
            
            List<ExportTicketViewItemDTO> exportTicketViewItemDTOs = buildExportTicketViewItemsDtoByCondition(admissionTicketInfo.getId());
            if(CollUtil.isNotEmpty(exportTicketViewItemDTOs)) {
                LOG.info("# ExportTicketViewItemDTO size:{}", exportTicketViewItemDTOs.size());
            }else {
                LOG.info("# ExportTicketViewItemDTO size null");
            }
            ProgressManager.updateProgressCurrent(60L, null);
            WriteSheet writeSheet = EasyExcel.writerSheet(1, "准考证操作记录").head(ExportTicketViewDTO.class).build();
            excelWriter.write(exportTicketViewDTOs, writeSheet);
            
            // 根据条件获取所有的工单列表
            WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "准考证操作记录明细").head(ExportTicketViewItemDTO.class).build();
            excelWriter.write(exportTicketViewItemDTOs, writeSheet2);
            excelWriter.finish();
            // 使用 easyExcel 写到 InputStream
            ProgressManager.updateProgressCurrent(80L, null);
            
            // 将文件上传到华为云
            log.info("# exportExamineeOperateList、文件{}生成成功", fileNamePreFix);
            String path = "admission/viewlist/" + fileNamePreFix;
            String fileUrl = cloudObsService.updateFile(path, achievementDetailListExcel);
            // 将文件字节数组上传到华为云
            log.info("# exportExamineeOperateList、文件{}上传华为云成功：{}", fileNamePreFix, fileUrl);
            
            boolean flag = achievementDetailListExcel.delete();
            if(!flag){
				log.info("# achievementDetailListExcel delete failed");
			}
            ProgressManager.updateProgressCurrent(100L, fileUrl);
        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
	}

	private List<ExportTicketViewDTO> buildExportTicketViewDtoByCondition(ExamineeTicketViewPageParam examineeTicketViewPageParam) {
		List<ExportTicketViewDTO> exportTicketViewDTOList = new ArrayList<>();
		boolean hasnext = true;
		int index = 1;
		int size = 1000;
		while (hasnext) {
			try {
				List<ExportTicketViewDTO> list = examineeOperateMapper.exportQueryTicketViewListPage(examineeTicketViewPageParam, index, size);
				if (CollUtil.isNotEmpty(list)) {
					List<ExportTicketViewDTO> viewDTOS = list.stream().parallel().map(data -> {
						ExportTicketViewDTO exportTicketViewDTO = new ExportTicketViewDTO();
						BeanUtils.copyProperties(data, exportTicketViewDTO);
						return exportTicketViewDTO;
					}).collect(Collectors.toList());
					exportTicketViewDTOList.addAll(viewDTOS);
					index++;
				} else {
					hasnext = false;
				}
			} catch (Exception e) {
				LOG.error("getExportTicketViewPage error", e);
				hasnext = false;
			}
		}
		return exportTicketViewDTOList;
	}
	

    private List<ExportTicketViewItemDTO> buildExportTicketViewItemsDtoByCondition(String admissionTicketInfoId) {
        List<ExportTicketViewItemDTO> exportTicketViewDTOList = new ArrayList<>();
        boolean hasnext = true;
        int index = 1;
        int size = 100;
        PageParam<ExportTicketViewItemDTO> pageParam = new PageParam<>();
        pageParam.setCurrent(index);
        pageParam.setSize(size);
        while (hasnext) {
            try {
                Page<ExportTicketViewItemDTO> pageData = examineeOperateMapper.getExportTicketViewPage(admissionTicketInfoId, pageParam);
                if (null != pageData && CollUtil.isNotEmpty(pageData.getRecords())) {
                    Optional.ofNullable(pageData).map(Page::getRecords).orElseGet(Lists::newArrayList).stream().parallel().forEach(data -> {
                        ExportTicketViewItemDTO exportTicketViewDTO = new ExportTicketViewItemDTO();
                        BeanUtils.copyProperties(data, exportTicketViewDTO);
                        
                        if(null != data.getExamineStartTime() && null != data.getExamineEndTime()) {
                            String examineStartTime = DateUtil.format(data.getExamineStartTime(), DatePattern.NORM_DATE_PATTERN);
                            String examineEndTime = DateUtil.format(data.getExamineEndTime(), DatePattern.NORM_DATE_PATTERN);
                            String mergeExamineDate = StrUtil.format("{}至{}",
                                    Optional.ofNullable(examineStartTime)
                                            .orElse(StrPool.DASHED),
                                    Optional.ofNullable(examineEndTime)
                                            .orElse(StrPool.DASHED));
                            exportTicketViewDTO.setExamineeTime(mergeExamineDate);
                        }
                        if(null != data.getGenerateStatus()) {
                            exportTicketViewDTO.setGenerateStatusDesc(GenerateStatusEnum.getDescByType(data.getGenerateStatus()));
                        }
                        exportTicketViewDTOList.add(exportTicketViewDTO);
                    });
                    index++;
                    pageParam.setCurrent(index);
                } else {
                    hasnext = false;
                }
            } catch (Exception e) {
                LOG.error("getExportTicketViewPage error", e);
                hasnext = false;
            }
        }
        return exportTicketViewDTOList;
    }
}
